<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
    }

    .swiper {
      width: 800px;
      height: 500px;

    }

    .swiper-wrapper {
      display: flex;
      height: 100%;

    }

    .swiper-item {
      flex-shrink: 0;
    }

    button {
      width: 100px;
      height: 30px;
    }
  </style>
</head>

<body>
  <div class="swiper">
    <div class="swiper-wrapper">
      <div class="swiper-item"></div>
      <div class="swiper-item"></div>
      <div class="swiper-item"></div>
      <div class="swiper-item"></div>
      <div class="swiper-item"></div>
    </div>
  </div>
  <button id="pre">pre</button>
  <button id="next">next</button>
  <script>
    let arr = [
      {
        src: "./static/1.jpg",
      },
      {
        src: "./static/2.jpg",
      },
      {
        src: "./static/3.jpg",
      },
      {
        src: "./static/4.jpg",
      },
      {
        src: "./static/5.jpg",
      },
    ];
    class Swiper {
      #classList = {
        swiperWrapper: 'swiper-wrapper',
        swiperItem: 'swiper-item'
      }
      swiperWrapperDom;
      swiperWrapperItemsDom;
      width;
      index = 0;
      position = {
        initPoint: 0,
        endPoint: 0,
        initTsf: 0,
        gap: 0
      };
      flag = false;//此flag用于做翻页节流的标识符；如果为true就代表正在翻页
      autoplayFlag = true;
      constructor(opt) {
        this.el = typeof opt.el ===
          "string" ? document.querySelector(opt.el) : opt.el;
        this.data = opt.data;
        this.autoplay = opt.autoplay || false;
        this.init()
      }
      init () {
        this.render();
        let timer = this.autoplay && this.autoplayHandler()
      }
      render () {
        this.swiperWrapperDom = getNode(this.el, this.#classList.swiperWrapper)[0];
        //获取dom
        this.swiperWrapperItemsDom = getNode(this.swiperWrapperDom, this.#classList.swiperItem);
        let testList = this.swiperWrapperDom.querySelectorAll("." + this.#classList.swiperItem);
        this.swiperWrapperItemsDom.forEach((item, index) => {
          item.style.width = this.el.clientWidth + 'px';
          this.width = this.el.clientWidth;
          item.style.height = this.el.clientHeight + 'px';
          let img = createImgDom(this.data[index].src);
          img.style.width = '100%';
          img.style.height = '100%';
          img.draggable = false;
          item.appendChild(img)
        })
        let firstDom = this.swiperWrapperItemsDom[0].cloneNode(true);
        let lastDom = this.swiperWrapperItemsDom[this.swiperWrapperItemsDom.length - 1].cloneNode(true);
        this.swiperWrapperDom.insertBefore(lastDom, this.swiperWrapperItemsDom[0]);
        this.swiperWrapperDom.appendChild(firstDom);
        this.swiperWrapperItemsDom = getNode(this.swiperWrapperDom, this.#classList.swiperItem)
        this.swiperWrapperDom.style.transform = `translateX(${-(this.index + 1) * this.width}px)`;
        this.el.style.overflow = 'hidden';
        this.event();
      }
      displace (index) {
        if (this.flag) return
        this.flag = true
        this.swiperWrapperDom.style.transition = `.3s`;
        this.swiperWrapperDom.style.transform = `translateX(${-(this.index + 1) * this.width}px)`;
        let timer = setTimeout(() => {
          this.swiperWrapperDom.style.transition = `0s`;
          if (this.index == -1 || this.index == this.data.length) {

            this.index = this.index == -1 ? this.data.length - 1 : 0;
            this.swiperWrapperDom.style.transform = `translateX(${-(this.index + 1) * this.width}px)`;

          }
          this.flag = false;

          clearTimeout(timer);
        }, 300)
      };
      event () {
        let dom = this.swiperWrapperDom;
        const mouseEnterHandler = () => {
          console.log(this.autoplayFlag)
          this.autoplayFlag = false
        }
        const clickHandler = function (e) {
          this.position.initPoint = parseInt(e.clientX);
          this.position.initTsf = parseInt(getComputedStyle(dom).getPropertyValue("transform").split(",")[4]);
          this.position.gap = 0;
          this.position.endPoint = 0;
          dom.addEventListener("mousemove", moveHandler, false);
          dom.addEventListener("mouseup", clear, false);
        }
        const moveHandler = (e) => {
          let position = this.position
          position.endPoint = parseInt(e.clientX);
          position.gap = (parseInt(e.clientX) - position.initPoint)
          let val = position.initTsf + position.gap;
          this.swiperWrapperDom.style.transform = `translateX(${val}px)`;
        }
        const clear = () => {
          let position = this.position;
          dom.removeEventListener("mousemove", moveHandler, false);
          if (position.gap == 0) return
          if (Math.abs(position.gap) < this.width / 3) {
            this.displace(this.index)
          } else {
            position.gap > 0 ? this.pre() : this.next();
            ;
          }
          position.gap = 0;

        }
        const leaveHandler = () => {
          clear();
          this.autoplayFlag = true;
        }
        dom.addEventListener("mousedown", clickHandler.bind(this), false);

        this.el.addEventListener("mouseleave", leaveHandler)
        this.el.addEventListener("mouseenter", mouseEnterHandler)
      }

      pre () {
        this.index--;
        this.displace(this.index)
      }
      next () {
        this.index++;
        this.displace(this.index)

      }
      autoplayHandler () {
        let timer = setInterval(() => {
          if (!this.autoplayFlag) return
          this.index++;
          this.displace(this.index)
        }, 3000)
        return timer
      }
    }

    //获取node节点方法
    function getNode (dom, className) {
      let res = [];
      dom.childNodes.forEach(item => {
        if (item.className == className) {
          res.push(item)
        }
      })
      return res
    }
    function createImgDom (src) {
      let img = document.createElement('img');
      img.src = src;
      return img
    }
    function debounce (callback, delay) {
      let timer = null;
      return function () {
        clearTimeout(timer)
        timer = setTimeout(() => {
          callback.apply(this, arguments);
        }, delay)
      }
    }
    let swiper = new Swiper({
      el: '.swiper',
      data: arr,
      autoplay: true
    })
    let flag = true;
    function throttle (fn, delay) {
      var timer;
      return function () {
        var _this = this;
        var args = arguments;
        if (timer) {
          return;
        } else {
          fn.apply(_this, args);
        }

        timer = setTimeout(function () {
          timer = null; // 在delay后执行完fn之后清空timer，此时timer为假，throttle触发可以进入计时器
        }, delay)
      }
    }
    pre.onclick = throttle(swiper.pre.bind(swiper), 1000);
    next.onclick = throttle(swiper.next.bind(swiper), 1000);
    console.log(swiper)
  </script>
</body>

</html>